package gameserver;

/*
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 * 
 * Credit goes to l2j-client project <https://code.google.com/p/l2jserver-client/> and l2j project <http://www.l2jserver.com/>
 */

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;

public class GameClientToServer extends Thread
{
	private DataOutputStream toServer;
	private DataInputStream fromClient;
	private Socket serverSocket;
	private Socket clientSocket;

	public GameClientToServer(Socket clientSocket, Socket serverSocket)
	{
		this.serverSocket = serverSocket;
		this.clientSocket = clientSocket;
	}

	@Override
	public void run()
	{
		try
		{
			fromClient = new DataInputStream(clientSocket.getInputStream());
			toServer = new DataOutputStream(serverSocket.getOutputStream());
			while (clientSocket.isConnected() && !clientSocket.isClosed() && serverSocket.isConnected() && !serverSocket.isClosed())
			{

				byte[] buf = new byte[2];
				int read = fromClient.read(buf);
				if (read < 0)
				{
					if (serverSocket != null && serverSocket.isConnected())
						serverSocket.close();
					if (clientSocket != null && clientSocket.isConnected())
						clientSocket.close();
					System.out.println("GameClientToServer: run(): Disconnected due to eond of stream in read");
					return;
				}
				else if (read != 2)
				{
					System.out.println("GameClientToServer: run(): Read less than 2 bytes for packet length, skipping info");
					continue;
				}
				int rawSize = Sbyte2int(buf[0]) + Sbyte2int(buf[1]) * 256;

				if (rawSize <= 0)
					continue;

				byte[] data = new byte[rawSize];

				read = fromClient.read(data, 2, rawSize - 2);
				if (read < 0)
				{
					if (serverSocket != null && serverSocket.isConnected())
						serverSocket.close();
					if (clientSocket != null && clientSocket.isConnected())
						clientSocket.close();
					System.out.println("GameClientToServer: data: Disconnected due to end of stream in read");
					return;
				}
				else
				{
					if (read != rawSize - 2)
					{
						System.out.println("Stream read returned only " + read + " of " + (rawSize - 2) + " bytes in total");
						while (read != rawSize - 2)
							read += fromClient.read(data, 2 + read, rawSize - 2 - read);

						System.out.println("Stream finally read " + read + " bytes of " + (rawSize - 2) + " bytes in total");
					}
				}

				try
				{
					data[0] = buf[0];
					data[1] = buf[1];
				}
				catch (ArrayIndexOutOfBoundsException e)
				{
					System.out.println("GameClientToServer: " + e.getLocalizedMessage());
					if (clientSocket.isConnected())
						clientSocket.close();
					return;
				}
				toServer.write(data);
				toServer.flush();
			}

		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		System.out.println("GameClientToServer: end");
	}

	private static int Sbyte2int(byte sb)
	{
		int wtrf = sb;
		if (wtrf < 0)
		{
			wtrf = 256 + wtrf;
		}
		return wtrf;
	}
}
